﻿/*
 * Copyright (c) 2011, Andrey Krupa
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of Krupa.Pro nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
using System;
using System.IO;
using System.Text;
using System.Web.Mvc;
using System.Xml;

namespace Krupa.Pro.Web.Utility.Composite
{
    public class CompositeView : IView
    {
        public String ViewPath { get; private set; }
        public CompositeConfig Config { get; private set; }
        public CompositeView(string viewPhysicalPath)
        {
            ViewPath = viewPhysicalPath;
            CompositeConfig config;
            using(var reader = new StreamReader(ViewPath))
            {
                using (var xmlReader = XmlReader.Create(reader))
                {
                    config = XmlSerialization.Serializer.Deserialize<CompositeConfig>(xmlReader);
                }
            }
            Config = config;
        }

        #region IView Members

        public virtual void Render(ViewContext viewContext, TextWriter writer)
        {
            foreach (var entry in Config.Entrys)
            {
                var encoding = entry.Encoding ?? Config.DefaultEncoding ?? Encoding.Default;
                var path = viewContext.HttpContext.Server.MapPath(entry.FileName);
                PreRenderEntry(viewContext, writer, encoding, path);
                RenderEntry(viewContext, writer, encoding, path);
                PostRenderEntry(viewContext, writer, encoding, path);
            }
            viewContext.HttpContext.Response.AddFileDependency(ViewPath);
            if(Config.ContentType!= String.Empty)
            {
                viewContext.HttpContext.Response.AddHeader("Content-Type", Config.ContentType);    
            }
            viewContext.HttpContext.Response.Cache.SetETagFromFileDependencies();
        }
        protected virtual void PreRenderEntry(ViewContext viewContext, TextWriter writer, Encoding encoding, String entryPath)
        {

        }
        protected virtual void RenderEntry(ViewContext viewContext, TextWriter writer, Encoding encoding, String entryPath)
        {
            using (var reader=new StreamReader(entryPath,encoding))
            {
                var buffer = new char[4096];
                int count;
                while ((count = reader.ReadBlock(buffer,0,buffer.Length))>0)
                {
                    writer.Write(buffer,0,count);
                }
            }
        }
        protected virtual void PostRenderEntry(ViewContext viewContext, TextWriter writer, Encoding encoding, String entryPath)
        {
            viewContext.HttpContext.Response.AddFileDependency(entryPath);
        }

        #endregion
    }
}